﻿
using BlazorMobile.Components;
using BlazorMobile.Helper;
using Org.Mozilla.Geckoview;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BlazorMobile.Droid.Helper
{
    internal static class WebExtensionHelper
    {
        private static int _counter = 0;

        private static int GenerateWebExtensionIdentity()
        {
            return _counter++;
        }

        internal class WebExtensionMetadata
        {
            internal WebExtensionMetadata(string id, string location)
            {
                Id = id;
                Location = location;
            }

            internal string Id { get; set; }

            internal string Location { get; set; }
        }

        private static Dictionary<int, List<WebExtensionMetadata>> _runtimeExtensionDico = new Dictionary<int, List<WebExtensionMetadata>>();

        private static bool RuntimeHasWebExtension(GeckoRuntime runtime, string webExtensionLocation)
        {
            int runtimeIdentity = runtime.GetHashCode();

            return _runtimeExtensionDico.ContainsKey(runtimeIdentity) && _runtimeExtensionDico[runtimeIdentity].Any(p => p.Location == webExtensionLocation);
        }

        private static void AddRuntimeWebExtensionReference(GeckoRuntime runtime, WebExtension webExtension)
        {
            int runtimeIdentity = runtime.GetHashCode();

            if (!_runtimeExtensionDico.ContainsKey(runtimeIdentity))
            {
                _runtimeExtensionDico.Add(runtimeIdentity, new List<WebExtensionMetadata>());
            }

            _runtimeExtensionDico[runtimeIdentity].Add(new WebExtensionMetadata(webExtension.Id, webExtension.Location));
        }

        /// <summary>
        /// Register the given WebExtension to the given runtime instance of a GeckoView
        /// This method is used to forward event based on WebExtension id to the right GeckoView instance
        /// The WebExtension id will be generated by this method
        /// </summary>
        internal static void RegisterWebExtension(BlazorGeckoView blazorGeckoView, GeckoRuntime runtime, string webExtensionLocation)
        {
            if (blazorGeckoView == null)
            {
                throw new ArgumentNullException(nameof(blazorGeckoView));
            }

            if (runtime == null)
            {
                throw new ArgumentNullException(nameof(runtime));
            }

            //We do a preliminary check if a same runtime on another GeckoView is used. We must not register a WebExtension twice if it is already present on a runtime. We assume that we are using our BlazorWebview as a solo-instance behavior
            if (RuntimeHasWebExtension(runtime, webExtensionLocation))
            {
                //Already registered. Ignore registration
                return;
            }

            //Get an unique identity
            int identity = GenerateWebExtensionIdentity();

            WebExtension webExtension = new WebExtension(webExtensionLocation, identity.ToString());

            //Register the given WebExtension to the runtime
            runtime.RegisterWebExtension(webExtension);

            //Register the WebExtension registration in our dictionnary
            AddRuntimeWebExtensionReference(runtime, webExtension);

            //Register the Webview with this identity attached to retrieve it later by WebExtension identity
            WebViewHelper.RegisterWebView(blazorGeckoView, identity);
        }
    }
}